import datetime
import sys
from typing import List, Dict

from sqlalchemy import Boolean, Column, DateTime, String, Index, text, TEXT, distinct, or_
from sqlalchemy.orm import Session, relationship

from core.logger import logger
from common.database import Base
from common.database import SessionMixin
from app.auth.models.auth_users_roles import AuthUsersRoles
from app.auth.models.auth_roles import AuthRoles
from app.auth.models.auth_permissions import AuthPermissions
from app.auth.models.auth_roles_permissions import AuthRolesPermissions

__all__ = ['AuthUsers']


class AuthUsers(Base, SessionMixin):
    """
    基于角色权限控制-用户表
    """
    __tablename__ = "auth_users"
    username = Column(String(255), nullable=False, comment="用户名称")
    auth_type = Column(String(128), nullable=False, comment="认证类型 ldap|mysql")
    hash_password = Column(String(128), nullable=False, comment='哈希密码')
    nick_name = Column(String(255), nullable=False, comment="昵称")
    avatar = Column(TEXT, default='https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', nullable=True, comment="头像")
    email = Column(String(255), nullable=True, comment="邮箱")
    mobile = Column(String(18), nullable=True, comment="手机号码")
    is_superuser = Column(Boolean, default=text('false'), nullable=False, comment="管理员状态")
    is_active = Column(Boolean, default=text('true'), nullable=False, comment="激活状态")
    auth_roles = relationship('AuthRoles', secondary=AuthUsersRoles, back_populates='auth_users', lazy='dynamic')
    create_time = Column(DateTime, default=datetime.datetime.now, nullable=False, comment="创建时间")
    update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, nullable=False,
                         comment="更新时间")

    __table_args__ = (
        Index('idx_auth_users_uuid', 'uuid', unique=True),
        Index('idx_auth_users_username', 'username', unique=True),
        {
            'mysql_engine': 'innodb',
            'mysql_charset': 'utf8mb4',
            'mysql_collate': 'utf8mb4_unicode_ci',
            'extend_existing': True,
            'mysql_row_format': 'dynamic',
        }
    )

    def __repr__(self):
        return "<uuid='{}',username='{}'>".format(self.uuid, self.username)

    # @classmethod
    # def get_paginate(cls, db: Session, page, per_page):
    #     result = db.query(cls).with_entities(cls.uuid, cls.username, cls.nick_name, cls.is_active, cls.is_superuser,
    #                                 cls.email,
    #                                 cls.mobile).paginate(page=page, per_page=per_page)
    #     result["fields"] = cls.get_display_field_meta()
    #     return result

    @classmethod
    def get_paginate(cls, db: Session, page: int, per_page: int, field: str, value: str) -> List[Dict]:
        try:
            search_field = []
            if value:
                for key, col in cls.__table__.c.items():
                    if field == "all" or key == field: search_field.append(col.like(f"%{value}%"))
            result = db.query(cls).filter(or_(*search_field)). \
                with_entities(cls.uuid, cls.username, cls.nick_name, cls.is_active, cls.is_superuser, cls.email,
                              cls.mobile).paginate(page=page, per_page=per_page)
        except Exception as e:
            logger.error(f'{sys._getframe().f_code.co_name} {e}')
            return []

        result["fields"] = cls.get_display_field_meta()
        return result

    @classmethod
    def get_by_uuid(cls, db: Session, uuid: int) -> Dict:
        return db.query(cls).filter(cls.uuid == uuid).to_dict_first()

    @classmethod
    def get_by_username(cls, db: Session, username: str) -> Dict:
        return db.query(cls).filter(cls.username == username).to_dict_first()

    @classmethod
    def get_roles_by_uuid(cls, db: Session, uuid: int) -> List[Dict]:
        return db.query(AuthRoles).with_entities(AuthRoles.uuid, AuthRoles.description).outerjoin(
            AuthUsersRoles).outerjoin(cls).filter(cls.uuid == uuid).to_dict()

    @classmethod
    def get_permissions_tags_by_uuid(cls, db: Session, uuid: int) -> List[List]:
        items = db.query(AuthPermissions).with_entities(distinct(AuthPermissions.tags).label("tag")).join(
            AuthRolesPermissions).join(AuthRoles).join(AuthUsersRoles).join(cls).filter(cls.uuid == uuid).all()
        return [cls.to_list(item) for item in items if item]

    @classmethod
    def get_permissions_by_uuid(cls, db: Session, uuid: int) -> List[Dict]:
        return db.query(AuthPermissions).with_entities(AuthPermissions.url, AuthPermissions.method).join(
            AuthRolesPermissions).join(AuthRoles).join(AuthUsersRoles).join(cls).filter(cls.uuid == uuid).to_dict()

    @classmethod
    def get_user_roles_paginate(cls, db: Session, page, per_page, field: str, value: str) -> List[Dict]:
        data = cls.get_paginate(db, page, per_page, field, value)
        for item in data.get('items'):
            user = db.query(cls).filter(cls.uuid == item.get('uuid')).first()
            if user.auth_roles:
                item.update({'user_roles': sorted(
                    user.auth_roles.with_entities(AuthRoles.uuid, AuthRoles.description).to_dict(),
                    key=lambda s: s.get('uuid'), reverse=False)})
            else:
                item.update({'user_roles': []})
        return data
